/* ============================================================== */
/* 矢量类 */
/* ============================================================== */
if(!window.Vector) {

window.Vector = (function(){
    function Vector(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    }

    /* ============================静态方法============================ */
    /**
     * 求两个矢量横纵坐标之和 
     * @param {Vector} a 矢量a
     * @param {Vector} b 矢量b
     * @return {Vector} 和矢量
     */
    Vector.add = function(a, b) {
        return new Vector(a.x + b.x, a.y + b.y);
    }

    /**
     * 求两个矢量横纵坐标之差
     * @param {Vector} a 矢量a
     * @param {Vector} b 矢量b
     * @return {Vector} 差矢量
     */
    Vector.sub = function(a, b) {
        return new Vector(a.x - b.x, a.y - b.y);
    }

    /**
     * 将指定矢量按指定缩放量进行缩放
     * @param {Vector} v 要放大基础矢量
     * @param {Number} s 缩放比例
     * @return {Vector} 缩放后的矢量
     */
    Vector.scale = function(v, s) {
        return new v.clone().scale(s);
    }

    /**
     * 横纵坐标值在[-1, 1)范围内随机取值的新矢量对象
     * @return {Vector} 随机横纵坐标的新矢量实例
     */
    Vector.random = function() {
        return new Vector(
            Math.random() * 2 - 1,
            Math.random() * 2 - 1
        );
    }
    /* ============================静态方法============================ */

    
    /* ============================原型对象============================ */
    Vector.prototype = {
        /**
         * 为当前调用矢量实例设置x，y属性
         * @param {Vector, Number} x 值矢量实例也可以是固定数值
         * @param {Number} y 若x不是Vecotr实例，则y必要，是固定值
         * @return {Vector} 调用实例本身
         */
        set: function(x, y) {
            if(typeof x === 'object') {
                y = x.y;
                x = x.x;
            }
            this.x = x || 0;
            this.y = y || 0;
            return this;
        },

        /**
         * 调用实例横纵值增加指定量
         * @param {Vector} v 增量矢量实例
         * @return {Vector} 调用实例本身
         */
        add: function(v) {
            this.x += v.x;
            this.y += v.y;
            return this;
        },

        /**
         * 调用实例x,y值减少指定量
         * @param {Vector} v 增量矢量实例
         * @return {Vector} 调用实例本身
         */
        sub: function(v) {
            this.x -= v.x;
            this.y -= v.y;
            return this;
        },

        /**
         * 将调用实例x,y属性按指定量缩放
         * @param {Number} s 缩放量
         * @return {Vector} 调用实例本身
         */
        scale: function(s) {
            this.x *= s;
            this.y *= s;
            return this;
        },

        /**
         * @return 主调矢量距离原点长度
         */
        length: function() {
            return Math.sqrt(this.x * this.x + this.y * this.y);
        },

        /**
         * @return 主调矢量实例坐标的平方和
         */
        lengthSq: function() {
            return this.x * this.x + this.y * this.y;
        },

        /**
         * 计算主调矢量点到指定矢量点的距离
         * @param {Vector} v 指定矢量点
         * @return 主调矢量点到指定矢量点的距离
         */
        distanceTo: function(v) {
            var dx = v.x - this.x,
                dy = v.y - this.y;
            return Math.sqrt(dx * dx + dy * dy);
        },

        /**
         * 计算主调矢量点和指定矢量点坐标差的平方和
         * @param {Vector} v 指定矢量点
         * @return 主调矢量点和指定矢量点坐标差的平方和
         */
        distanceToSq: function(v) {
            var dx = v.x - this.x,
                dy = v.y - this.y;
            return dx * dx + dy * dy;
        },

        /**
         * 将长度缩为1，得到单位向量
         * @return {Vector} x，y值比值化，this.x = cos(a), this.y = sin(a)
         */
        normalize: function() {
            var m = Math.sqrt(this.x * this.x + this.y * this.y);
            if(m) {
                this.x /= m;
                this.y /= m;
            }
            return this;
        },

        /**
         * @return {Number} 主调矢量点到原点的连线与x轴的夹角度数
         */
        angle: function() {
            return Math.atan2(this.y, this.x);
        },

        /**
         * @return {Number} 主调矢量点与指定矢量点的连线与水平方向夹角的度数
         */
        angleTo: function(v) {
            var dx = v.x - this.x,
                dy = v.y - this.y;
            return Math.atan2(dy, dx); 
        },

        lerq: function(v, s) {
            this.x += (v.x - this.x) * s;
            this.y += (v.y - this.y) * s;
            return this;
        },

        clone: function() {
            return new Vector(this.x, this.y);
        }
    }
    /* ============================原型对象============================ */

    return Vector;
})()

} else {
    throw new Error('Vector被占用');
}